package Comp;

/**
 * This class converts an infix expression to a prefix expression.
 * <p><b>Original Author:</b>  Yogesh Jindal
 */
public class Prefix {
    
    private int[] getIndexOfInnerParenthesis(String[] array){
        int begin_index=-1,end_index=-1;
        for(int index=0; index<array.length; index++){
            if(array[index].contentEquals("(")){
                begin_index = index;
            }
            if(array[index].contentEquals(")")){
                end_index = index; 
                break;
            }
        }
        int index_array[] = new int[2];
        index_array[0]=begin_index; index_array[1]=end_index;
        return index_array;
    }
    
    /**
     * This function chops out everything from begin_index till end_index-1 in the String array[]
     * and then puts the prefix at end_index.
     * <p>
     * Modified Log:<br>
     * 5/10/08 - Edited documentation<br>
     * <p>
     * Error Condition tested:<br> 
     * None<br>
     * <p>
     * Creation Date : May 5,2008
     * <p>
     * <b>Original Author:</b> Yogesh Jindal
     * @param array  Any String[].
     * @param prefix  A prefix String.
     * @param begin_index  The begin_index.
     * @param end_index  The end_index.
     * @return Returns a new modified String[].
     */
    private String[] modifyArray(String[] array, String prefix, int begin_index, int end_index){
        int length = begin_index + array.length-end_index;
        String mod_arr[] = new String[length];
        int index=0;
        for(index=0; index<begin_index; index++){
            mod_arr[index] = array[index];
        }
            mod_arr[index] = prefix;
            index++;
        for(int index2=end_index+1; index2<array.length; index2++){
            mod_arr[index] = array[index2]; 
            index++;
        }        
        return mod_arr;
    }
    
    /**
     * This function is called from convToPrefix(String[]) if the infix String has parenthesis.
     * <p>
     * Modified Log:<br>
     * None<br>
     * <p>
     * Error Condition tested:<br>
     * None<br>
     * <p>
     * Creation Date: May 5,2008
     * <p>
     * <b>Original Author:</b> Yogesh Jindal
     * @param array The infix String array with parenthesis.
     * @return Returns the prefix String.
     */
    private String parenthesisCase(String[] array){
        while(1==1){            
            int index[] = getIndexOfInnerParenthesis(array);
            if(index[0]==index[1]){
                if(array.length==1){
                    return array[0];
                }else{                    
                    return noParenthesisCase(array);                    
                }
            }else{
                String temp[] = new String[index[1]-index[0]-1];
                for(int i=0; i<temp.length; i++){
                    temp[i]=array[index[0]+1+i];
                }
                String temp2 = noParenthesisCase(temp);                
                array = modifyArray(array,temp2,index[0],index[1]);
                temp2="";
            }
        }
    }
    
    /**
     * This function is called from convToPrefix(String[]) if the infix String has no parenthesis.
     * <p>
     * Modified Log:<br>
     * 5/10/08 - Edited documentation - Keith Hill<br>
     * <p>
     * Error Condition tested:<br>
     * None<br>
     * <p>
     * Creation Date : May 5,2008
     * <p>
     * <b>Original Author:</b> Yogesh Jindal
     * @param array The infix String array without parenthesis.
     * @return Returns the prefix String.
     */
    private String noParenthesisCase(String[] array){       
        NoParenthesis no_parenthesis_instance = new NoParenthesis();
        return no_parenthesis_instance.handleNoParenthesis(array);        
    }
    
    /**
     * This function converts the infix String[] to prefix String.
     * <p>
     * Modified Log:<br>
     * 5/10/08 - edited documentation - Keith Hill<br>
     * <p>
     * Error Condition tested:<br>
     * None<br>
     * <p>
     * Creation Date : May 4,2008
     * <p>
     * <b>Original Author:</b> Yogesh Jindal
     * <p>
     * @param input_array The String array to be converted to prefix String.
     * @return Returns a prefix string not a prefix array.
     */   
    public String convToPrefix(String[] input_array){
        String temp = "";
        for(int index=0; index<input_array.length; index++){
            temp += input_array[index];
        }
        if(temp.contains("(")){            
            return parenthesisCase(input_array);
        }else{            
            return noParenthesisCase(input_array);
        }
    }
    
    /**
     * This function checks if the parameter string is an operator out of - + * / 
     * <p>
     * Modified Log:<br>
     * 5/10/08 - Edited documentation - Keith Hill<br>
     * <p>
     * Error Condition tested:<br>
     * None<br>
     * <p>
     * Creation Date : May 4,2008
     * <p>
     * <b>Original Author:</b> Yogesh Jindal
     * @param check_operator The string to be checked for an operator.
     * @return Returns 1 for an operator else returns 0.
     */    
    private int isOperator(String check_operator){
        String[] operators = {"+","-","*","/"};
        for(int index=0; index<operators.length; index++){
            if(operators[index].contentEquals(check_operator)){
                return 1;
            }
        }
        return 0;
    }
    
    /**
     * This function is used when the array does not include any parenthesis.
     * <p>
     * Modified Log:<br>
     * 5/10/08 - Added documentation - Keith Hill<br>
     * <p>
     * Error Condition tested:<br>
     * None<br>
     * <p>
     * Creation Date : May 4,2008
     * <p>
     * <b>Original Author:</b> Yogesh Jindal
     * @param in_array the incoming array.
     * @return Returns the array without parenthesis.
     */    
    private String[] getNonParenthesisArray(String[] in_array){
        int num_parenthesis=0;
        for(int index=0; index<in_array.length; index++){
            if(in_array[index].contentEquals("(") || in_array[index].contentEquals(")")){
                num_parenthesis++;
            }
        }
        if(num_parenthesis==0){
            return in_array;
        }
        int counter=0;
        String[] non_paren_string = new String[in_array.length-num_parenthesis];
        for(int index=0; index<in_array.length; index++){
            if(in_array[index].contentEquals("(") || in_array[index].contentEquals(")")){
                
            }else{
                non_paren_string[counter] = in_array[index];
                counter++;
            }
        }
        return non_paren_string;
    }
    
    /**
     * This function converts the Prefix String to Prefix String Array.
     * <p>
     * Modified Log:
     * 5/10/08 - Edited documentation - Keith Hill<br>
     * <p>
     * Error Condition tested:<br>
     * None<br>
     * <p>
     * Creation Date : May 5,2008
     * <p>
     * <b>Original Author:</b> Yogesh Jindal.<br>
     * @param in_array Original infix String Array.
     * @param out_string Prefix String.
     * @return Returns the Prefix String array.
     */
    public String[] preFixStringToArray(String[] in_array, String out_string){
        in_array = getNonParenthesisArray(in_array);
        int in_array_label_pointer=0;
        String[] out_array = new String[in_array.length];
        for(int index=0; index<out_array.length; index++){
            if(isOperator(String.valueOf(out_string.charAt(0)))==1){
                out_array[index] = String.valueOf(out_string.charAt(0));
                out_string = out_string.substring(1);
            }else{
                 while(isOperator(in_array[in_array_label_pointer])==1){
                     in_array_label_pointer++;
                 }
                 int temp_label_len = in_array[in_array_label_pointer].length();
                 out_array[index] = out_string.substring(0, temp_label_len);
                 out_string = out_string.substring(temp_label_len);
                 in_array_label_pointer++;
            }
        }
        return out_array;
    }
    
    public static void main(String[] args){//handle the overflow exception
        /*
        Prefix prefix_instance = new Prefix();        
        String[] in_array = {"label","+","a","+","b"};
        String out_string = prefix_instance.convToPrefix(in_array);
        System.out.println(out_string);
        String[] out_array = prefix_instance.preFixStringToArray(in_array,out_string);        
        for(int index=0; index<out_array.length; index++){
            System.out.println(out_array[index]);
        }*/
    }
}